<?php
declare (strict_types = 1);

namespace app\common\model\System;

use app\common\model\Common;
use Library\Helper;
use think\facade\Cache;

class Regions extends Common
{
    // 主键
    protected $pk = 'region_id';
    // 开启自动写入时间戳字段
    protected $autoWriteTimestamp = true;
    // 自定义的软删除
    public $is_delete = 0; // 软删除

    public function getRegionByIds(array $region_ids)
    {
        return $this->whereIn($this->pk, $region_ids)->select();
    }

    public function getIdByName(string $name): int
    {
        return $this->where('name', $name)->value('region_id', 0);
    }

    public function getNameByIds(array $region_ids) : array
    {
        $list = $this->getRegionByIds($region_ids)->toArray();
        $data = array_column($list, 'name', $this->pk);
        $data[0] = '';
        return $data;
    }

    public function getSelectLists(array $where = [], $sort = 'ASC', string $fileds = '*')
    {
        $list = parent::getSelectLists($where, $sort, $fileds);
        return list_to_tree($list->toArray(), 'region_id', $parent_id = 'parent_id', $child = '_child');
    }

    // 当前数据版本号
    private static $version = '1.0.0';

    /**
     * 获取所有地区(树状结构)
     * @return mixed
     */
    public static function getCacheTree()
    {
        return static::getCacheData('tree');
    }

    /**
     * 获取所有地区列表
     * @return mixed
     */
    public static function getCacheAll()
    {
        return static::getCacheData('all');
    }

    /**
     * 获取所有地区的总数
     * @return mixed
     */
    public static function getCacheCounts()
    {
        return static::getCacheData('counts');
    }

    /**
     * 获取缓存中的数据(存入静态变量)
     * @param null $item
     * @return array|mixed
     */
    private static function getCacheData($item = null)
    {
        static $cacheData = [];
        if (empty($cacheData)) {
            $static = new static;
            $cacheData = $static->regionCache();
        }
        if (is_null($item)) {
            return $cacheData;
        }
        return $cacheData[$item];
    }

    /**
     * 获取地区缓存
     * @return array|mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    private function regionCache()
    {
        // 缓存的数据
        $complete = Cache::get('region');
        // 如果存在缓存则返回缓存的数据，否则从数据库中查询
        // 条件1: 获取缓存数据
        // 条件2: 数据版本号要与当前一致
        if (
            !empty($complete)
            && isset($complete['version'])
            && $complete['version'] == self::$version
        ) {
            return $complete;
        }
        // 所有地区
        $allList = $tempList = $this->getAllList();
        // 已完成的数据
        $complete = [
            'all' => $allList,
            'tree' => $this->getTreeList($allList),
            'counts' => $this->getCount($allList),
            'version' => self::$version,
        ];
        // 写入缓存
        Cache::tag('cache')->set('region', $complete);
        return $complete;
    }

    private static function getCount($allList)
    {
        $counts = [
            'total' => count($allList),
            'province' => 0,
            'city' => 0,
            'region' => 0,
        ];
        $level = [1 => 'province', 2 => 'city', 3 => 'region'];
        foreach ($allList as $item) {
            $counts[$level[$item['level']]]++;
        }
        return $counts;
    }

    /**
     * 格式化为树状格式
     * @param $allList
     * @return array
     */
    private function getTreeList($allList)
    {
        $treeList = [];
        foreach ($allList as $pKey => $province) {
            if ($province['level'] == 1) {    // 省份
                $treeList[$province['region_id']] = $province;
                unset($allList[$pKey]);
                foreach ($allList as $cKey => $city) {
                    if ($city['level'] == 2 && $city['parent_id'] == $province['region_id']) {    // 城市
                        $treeList[$province['region_id']]['city'][$city['region_id']] = $city;
                        unset($allList[$cKey]);
                        foreach ($allList as $rKey => $region) {
                            if ($region['level'] == 3 && $region['parent_id'] == $city['region_id']) {    // 地区
                                $treeList[$province['region_id']]['city'][$city['region_id']]['region'][$region['region_id']] = $region;
                                unset($allList[$rKey]);
                            }
                        }
                    }
                }
            }
        }
        return $treeList;
    }

    /**
     * 从数据库中获取所有地区
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    private function getAllList()
    {
        $list = self::deleteWhere()
                    ->field('region_id, parent_id, name, level')
                    ->select()
                    ->toArray();
        return Helper::arrayColumn2Key($list, 'region_id');
    }

    /**
     * 获取指定指定地址下所有子id
     * @param $parent_id
     * @param array $all
     * @return array
     */
    public static function getSubRegionId($parent_id, $all = [])
    {
        $arrIds = [$parent_id];
        empty($all) && $all = self::getCacheAll();
        foreach ($all as $key => $item) {
            if ($item['parent_id'] == $parent_id) {
                unset($all[$key]);
                $subIds = self::getSubRegionId($item['parent_id'], $all);
                !empty($subIds) && $arrIds = array_merge($arrIds, $subIds);
            }
        }
        return $arrIds;
    }
}
